using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Tools.SubStream {
    public class MuxerSubStream : System.IO.Stream {
        protected StreamMuxer streamMuxer;
        protected Range range;
        protected String name;

        protected long position;

        public String Name {
            get {
                return this.name;
            }

        }

        public MuxerSubStream ( StreamMuxer streamMuxer, Range range, String name ) {
            this.streamMuxer = streamMuxer;
            this.range = range;
            this.name = name;
        }


        public System.IO.Stream MasterStream {
            get {
                return this.streamMuxer.InnerStream;
            }
        }

        public Range Range {
            get {
                return this.range;
            }
        }

        //****** Stream Implementation ******


        public override bool CanRead {
            get {
                return this.MasterStream.CanRead;
            }
        }

        public override bool CanSeek {
            get {
                return this.MasterStream.CanSeek;
            }
        }

        public override bool CanWrite {
            get {
                return this.MasterStream.CanWrite;
            }
        }

        public override void Flush ( ) {
            this.MasterStream.Flush( );
        }

        public override long Length {
            get {
                Range r = new Range( this.range );
                r.To = Math.Min( r.To, this.MasterStream.Length );
                return r.Length;
            }

        }

        public override long Position {
            get {
                return this.position;
            }
            set {
                this.position = value;
            }
        }

        public override int Read ( byte[] buffer, int offset, int count ) {
            if ( count < 0 ) {
                return -1;
            }
            try {
                System.IO.Stream str = Synchronized( this.MasterStream );

                int read;
                //lock ( str ) {
                //Tools.Debugging.Debug.logger.Log( "start read " + this.Name );

                long maxRead = this.Range.Length - this.Position;
                count = Math.Min( ( int ) maxRead, count );

                str.Position = this.Range.From + this.Position;
                read = str.Read( buffer, offset, count );
                this.Position = str.Position - this.Range.From;

                //Tools.Debugging.Debug.logger.Log( "end read " + this.Name );
                //}

                //Console.WriteLine( "this.Position: {0}, str.Position: {1}, count; {2}, read: {3}", this.Position, str.Position, count, read );
                return read;

            } catch ( Exception e ) {
                Console.WriteLine( e.StackTrace );
                throw e;
            }

        }

        public override long Seek ( long offset, SeekOrigin origin ) {

            switch ( origin ) {
                case SeekOrigin.Begin:
                    this.Position = offset;
                    break;
                default:
                case SeekOrigin.Current:
                    this.Position += offset;
                    break;
                case SeekOrigin.End:
                    this.Position = this.Range.Length - offset;
                    break;
            }
            return this.Position;
        }

        public override void SetLength ( long value ) {
            throw new NotSupportedException( "SetLength method is not supported" );
            //throw new NotImplementedException( "The method or operation is not implemented." );
        }

        public override void Write ( byte[] buffer, int offset, int count ) {

            long innerPosition = this.Range.From + this.Position;
            Stream str = this.MasterStream;

            //lock ( str ) {
            str.Position = innerPosition;
            str.Write( buffer, offset, count );
            this.Position = str.Position - this.Range.From;
            //}



        }

        //public override int ReadByte ()
        //{
        //    Console.WriteLine( this.Position );
        //    if( this.Position > 90000 )
        //    {
        //        throw new Exception( "duzy position" );
        //    }

        //    if( this.Position < this.Range.Length )
        //    {
        //        return base.ReadByte();
        //    }
        //    else
        //    {
        //        return -1;
        //    }
        //}

    }


}